import json
import time

from django import http
from django.http import JsonResponse
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils import timezone
from django.views import View
from django_redis import get_redis_connection

from goods.models import SKU
from orders.models import OrderInfo, OrderGoods
from users.models import Address
from django.db import transaction
from django.http import HttpResponseForbidden

class OrderSettlementView(LoginRequiredMixin, View):
    def get(self, request):
        # 获取订单页面
        # 渲染结算页面地址内容
        user = request.user

        # 取地址,
        addresses = Address.objects.filter(user=user, is_deleted=False)

        # 从redis中取购物车的信息
        redis_client = get_redis_connection('carts')
        cart_redis = redis_client.hgetall('cart_%s' % user.id)  # {sku_id:count}
        cart_selected = redis_client.smembers('selected_%s' % user.id)  # {sku_id}

        # 遍历购物车, 组织sku的信息
        # total_count 总件数
        total_count = 0
        # total_amount 总价
        total_amount = 0
        # freight 运费 10
        freight = 10
        # payment_amount  总费用,  总价+运费
        payment_amount = 0
        # 遍历的时候, 需要把小计价格,累加到 总价中,
        sku_list = []
        for sku_id in cart_selected:
            sku = SKU.objects.get(id=sku_id)
            sku_data = {
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image_url.url,
                'price': sku.price,
                'count': int(cart_redis[sku_id]),
                'amount': sku.price * int(cart_redis[sku_id])
            }
            sku_list.append(sku_data)
            total_count += sku_data['count']
            total_amount += sku_data['amount']
            payment_amount += sku_data['amount']

        payment_amount += freight

        context = {
            'addresses': addresses,
            'default_address_id': user.default_address_id,
            'skus': sku_list,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': payment_amount,
        }

        return render(request, 'place_order.html', context=context)


class OrderCommitView(LoginRequiredMixin, View):
    def post(self, request):
        # 提交订单
        # 1, 接收数据
        data = json.loads(request.body.decode())
        address_id = data.get('address_id')  # 地址id
        pay_method = data.get('pay_method')  # 编号, 1,2

        # 2, 校验数据
        if not all([address_id, pay_method]):
            return JsonResponse({'code': 9999, 'errmsg': '参数不全'})

        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 9999, 'errmsg': '地址有误'})

        if not pay_method in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return JsonResponse({'code': 9999, 'errmsg': '支付方式不正确'})

        # 判断购物车数据
        user = request.user
        redis_client = get_redis_connection('carts')
        cart_redis = redis_client.hgetall('cart_%s' % user.id)
        cart_selected = redis_client.smembers('selected_%s' % user.id)

        if len(cart_selected) < 1:
            return JsonResponse({'code': 9999, 'errmsg': '请选择商品'})

        for sku_id in cart_selected:
            if sku_id not in cart_redis:
                return JsonResponse({'code': 9999, 'errmsg': '商品数量有误'})

        # 3, 处理业务
        pass
        # 3,1 保存订单
        # order_id 年月日时分秒 9位的user_id
        order_id = "%s%09d" % (timezone.localtime().strftime('%Y%m%d%H%M%S'), user.id)

        # user
        user = request.user

        # total_count
        total_count = 0

        # total_amount
        total_amount = 0

        # freight
        freight = 10

        # pay_method
        # status  订单状态
        if int(pay_method) == OrderInfo.PAY_METHODS_ENUM['ALIPAY']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']

        # 增加事务
        with transaction.atomic():
            # with块内的数据都会被记录在事务中, 可以提供回滚操作
            # 创建存盘点
            save_point = transaction.savepoint()

            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address_id=address_id,
                    total_count=total_count,
                    total_amount=total_amount,
                    freight=freight,
                    pay_method=pay_method,
                    status=status
                )

                # 3,2 保存订单商品
                # order
                # 遍历选择的商品, 组织数据, 保存订单商品
                for sku_id in cart_selected:
                    while True:
                        sku = SKU.objects.get(id=sku_id)

                        count = int(cart_redis[sku_id])

                        # 锁定原始库存的数值  和销量数值, 记录
                        old_stock = sku.stock
                        old_sales = sku.sales

                        # 1, 判断库存
                        if count > sku.stock:
                            transaction.savepoint_rollback(save_point)
                            return JsonResponse({'code': 9999, 'errmsg': '库存不足'})

                        # 延迟保存
                        # time.sleep(5)

                        # 2, 减少库存, 增加销量
                        # 找到原始库存原始销量的那条数据, 更新成新的库存和销量
                        new_stock = old_stock - count
                        new_sales = old_sales + count
                        # 更新数据库
                        res = SKU.objects.filter(id=sku_id, stock=old_stock, sales=old_sales).update(stock=new_stock, sales=new_sales)
                        print(res)
                        if res == 0:
                            # 没有更新成功
                            # transaction.savepoint_rollback(save_point)
                            # return JsonResponse({'code': 9999, 'errmsg': '系统繁忙'})
                            continue

                        break

                    # 3, 累加到订单信息中
                    order.total_count += count
                    order.total_amount += count * sku.price

                    OrderGoods.objects.create(
                        order=order,
                        sku=sku,
                        count=int(cart_redis[sku_id]),
                        price=sku.price
                    )

                order.save()

            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_point)
                return JsonResponse({'code': 9999, 'errmsg': '下单失败'})

            transaction.savepoint_commit(save_point)

            # 购物车中清理已经结算的商品
            redis_client.hdel('cart_%s' % user.id, *cart_selected)
            redis_client.srem('selected_%s' % user.id, *cart_selected)

        # 4, 返回响应

        res = {
            'code': 0,
            'errmsg': '成功',
            'order_id': order.order_id
        }
        return JsonResponse(res)
        pass


class OrderSuccessView(LoginRequiredMixin, View):
    def get(self,request):
        # 展示下单成功页面
        # 1, 接收数据
        data = request.GET
        order_id = data.get('order_id')
        payment_amount = data.get('payment_amount')
        pay_method = data.get('pay_method')

        # 2, 校验数据
        if not all([order_id, pay_method, payment_amount]):
            return HttpResponseForbidden('参数不全')

        try:
            order = OrderInfo.objects.get(order_id=order_id)
        except Exception as e:
            print(e)
            return HttpResponseForbidden('订单号不正确')

        # 3, 处理业务

        # 4, 返回响应
        context = locals()
        return render(request, 'order_success.html', context=context)

        pass


class OrderCommentView(LoginRequiredMixin, View):
    """订单商品评价"""

    def get(self, request):
        """展示商品评价页面"""
        # 接收参数
        order_id = request.GET.get('order_id')
        # 校验参数
        try:
            OrderInfo.objects.get(order_id=order_id, user=request.user)
        except OrderInfo.DoesNotExist:
            return http.HttpResponseNotFound('订单不存在')

        # 查询订单中未被评价的商品信息
        try:
            uncomment_goods = OrderGoods.objects.filter(order_id=order_id, is_commented=False)
        except Exception:
            return http.HttpResponseServerError('订单商品信息出错')

        # 构造待评价商品数据
        uncomment_goods_list = []
        for goods in uncomment_goods:
            uncomment_goods_list.append({
                'order_id':goods.order.order_id,
                'sku_id':goods.sku.id,
                'name':goods.sku.name,
                'price':str(goods.price),
                'default_image_url':goods.sku.default_image_url.url,
                'comment':goods.comment,
                'score':goods.score,
                'is_anonymous':str(goods.is_anonymous),
            })

        # 渲染模板
        context = {
            'skus': uncomment_goods_list
        }
        return render(request, 'goods_judge.html', context)

    def post(self, request):
        """评价订单商品"""
        # 接收参数
        json_dict = json.loads(request.body.decode())
        order_id = json_dict.get('order_id')
        sku_id = json_dict.get('sku_id')
        score = json_dict.get('score')
        comment = json_dict.get('comment')
        is_anonymous = json_dict.get('is_anonymous')
        # 校验参数
        if not all([order_id, sku_id, score, comment]):
            return http.HttpResponseForbidden('缺少必传参数')
        try:
            OrderInfo.objects.filter(order_id=order_id, user=request.user,
                                     status=OrderInfo.ORDER_STATUS_ENUM['UNCOMMENT'])
        except OrderInfo.DoesNotExist:
            return http.HttpResponseForbidden('参数order_id错误')
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('参数sku_id错误')
        if is_anonymous:
            if not isinstance(is_anonymous, bool):
                return http.HttpResponseForbidden('参数is_anonymous错误')

        # 保存订单商品评价数据
        OrderGoods.objects.filter(order_id=order_id, sku_id=sku_id, is_commented=False).update(
            comment=comment,
            score=score,
            is_anonymous=is_anonymous,
            is_commented=True
        )

        # 累计评论数据
        sku.comments += 1
        sku.save()
        sku.spu.comments += 1
        sku.spu.save()

        # 如果所有订单商品都已评价，则修改订单状态为已完成
        if OrderGoods.objects.filter(order_id=order_id, is_commented=False).count() == 0:
            OrderInfo.objects.filter(order_id=order_id).update(status=OrderInfo.ORDER_STATUS_ENUM['FINISHED'])

        return http.JsonResponse({'code': 0, 'errmsg': '评价成功'})